package main

import (
	"fmt"
	"github.com/shopspring/decimal"
	"strconv"
	"strings"
	"unsafe"
)

// 数据类型：基本数据类型和复合数据类型
func main() {
	// 定义int类型
	var num int = 128
	fmt.Printf("num=%v, 类型：%T \n", num, num)

	// int8的范围演示
	var num8 int8 = 127
	//var num8 int8 = 128 错误，超出最大范围
	fmt.Printf("num8=%v, 类型：%T \n", num8, num8)

	// unsafe.Sizeof() 查看不同长度的整型在内存里面的存储空间
	fmt.Println("int8:", unsafe.Sizeof(int8(0)))

	// uint8的范围（0-255）
	var num88 uint8 = 255
	// var num88 uint8 = -2 错误，超出最大范围
	fmt.Printf("num88=%v, 类型：%T \n", num88, num88)

	// int类型转换：高位向低位转换时需要不能大于低位的取值范围
	var a1 int32 = 10
	var a2 int64 = 21
	fmt.Println(a1 + int32(a2))

	// 数字字面量语法： %d 表示10进制输出，%b 表示2进制输出，%o 表示8进制输出，%x 表示16进制输出
	num81 := 16
	fmt.Printf("num=%v 类型:%T \n", num81, num81)
	fmt.Println("num81:", unsafe.Sizeof(num81)) // 表示64位的计算机，int就是int64，占用8个字节

	fmt.Printf("原样输出 num81=%v \n", num81)   // 原样输出
	fmt.Printf("十进制输出 num81=%d \n", num81)  // 十进制输出
	fmt.Printf("二进制输出 num81=%b \n", num81)  // 二进制输出
	fmt.Printf("八进制输出 num81=%o \n", num81)  // 八进制输出
	fmt.Printf("十六进制输出 num81=%x \n", num81) // 十六进制输出

	// 浮点型
	var b float32 = 3.14
	fmt.Printf("b=%v--%f, 类型：%T \n", b, b, b)
	fmt.Println("b:", unsafe.Sizeof(b))

	var b64 float64 = 3.14
	fmt.Printf("b64=%v--%f, 类型：%T \n", b64, b64, b64)
	fmt.Println("b64:", unsafe.Sizeof(b64))

	// %f 输出float类型 %.2f 输出数据的时候保留2位小数
	fmt.Printf("b=%v--%.2f, 类型：%T \n", b, b, b)

	// 64位操作系统中默认输出float类型为64位
	f1 := 3.14
	fmt.Printf("f1=%v, 类型：%T \n", f1, f1)

	// 科学计数法表示浮点类型
	var f2 = 3.14e2 // 3.14e2 = 3.14 * 10^2
	fmt.Printf("f2=%v, 类型：%T \n", f2, f2)

	var f3 = 3.14e-2 // 3.14e-2 = 3.14 * 10^-2
	fmt.Printf("f3=%v, 类型：%T \n", f3, f3)

	// float精度丢失问题
	var f4 float64 = 1129.6
	fmt.Println("精度丢失：", f4*100)
	// 解决精度丢失问题，使用开源包：http://github.com/shopspring/decimal
	var num1 float64 = 3.1
	var num2 float64 = 4.2
	d1 := decimal.NewFromFloat(num1).Add(decimal.NewFromFloat(num2))
	fmt.Println("d1的值：", d1)

	// int类型转换为float类型
	i := 10
	j := float64(i)
	fmt.Printf("b=%v, 类型：%T \n", j, j)

	// 布尔类型
	var bool1 bool = true
	fmt.Printf("bool1=%v, 类型：%T \n", bool1, bool1)

	// 字符串
	var str1 string = "hello world"
	fmt.Printf("str1=%v, 类型：%T \n", str1, str1)
	// 多行字符串
	var str2 = `
		hello world1
		hello world2
		hello world3
	`
	fmt.Println(str2)

	// 字符串分割
	str3 := "hello world"
	fmt.Println(str3[0:5])
	fmt.Println(str3[6:])
	arr := strings.Split(str3, " ")
	for _, v := range arr {
		fmt.Println(v)
	}
	// 字符串拼接
	str4 := strings.Join(arr, "*")
	fmt.Println(str4)
	// 前缀和后缀判断
	fmt.Println(strings.HasPrefix(str3, "hello"))
	fmt.Println(strings.HasSuffix(str3, "world"))
	// 字符串出现位置，下标从0开始，查不到返回-1
	fmt.Println(strings.Index(str3, "world"))
	fmt.Println(strings.LastIndex(str3, "world"))

	// 字符
	var c1 byte = 'a'
	// 默认输出ASCII码的值
	fmt.Printf("c1=%v, 类型：%T \n", c1, c1)
	// 原样输出字符
	fmt.Printf("c1=%c, 类型：%T \n", c1, c1)
	// 一个汉字占用 3个字节（utf-8，如果是gbk占用2个字节，go默认utf-8），一个字母占用一个字节
	str5 := "hello world"
	fmt.Println("str5长度:", len(str5))
	str6 := "你"
	fmt.Println("str6长度:", len(str6))
	str7 := '国'
	// Unicode编码10进制
	fmt.Printf("str7=%v, 类型：%T \n", str7, str7)
	// 原样输出
	fmt.Printf("str7=%c, 类型：%T \n", str7, str7)

	// Sprintf 使用需要注意转换的格式：int 为%d，float 为%f，bool 为%t，byte 为%c

	// 通过 strconv 把其他类型转换为字符串
	str8 := strconv.FormatInt(int64(1), 10)
	fmt.Printf("strconv.FormatInt(1, 10)=%v, 类型：%T \n", str8, str8)
}

/*
	基本数据类型：整型、浮点型、布尔型、字符串
	- 整型 默认 0
	-- 有符号整型按长度分为：int8、int16、int32、int64
	-- 无符号整型按长度分为：uint8、uint16、uint32、uint64
	---- int8: (-128 ~ 127) -2^7 ~ 2^7-1 占用的字节数是1
	---- int16: (-32768 ~ 32767) -2^15 ~ 2^15-1 占用的字节数是2
	---- int32: (-2147483648 ~ 2147483647) -2^31 ~ 2^31-1 占用的字节数是4
	---- int64: (-9223372036854775808 ~ 9223372036854775807) -2^63 ~ 2^63-1 占用的字节数是8
	---- uint8: (0 ~ 255) 0 ~ 2^8-1 占用字节数是1
	---- uint16: (0 ~ 65535) 0 ~ 2^16-1 占用字节数是2
	---- uint32: (0 ~ 4294967295) 0 ~ 2^32-1 占用字节数是4
	---- uint64: (0 ~ 18446744073709551615) 0 ~ 2^64-1 占用字节数是8

	- 浮点型 默认 0
	-- float32: 32位浮点数，占用4个字节，范围是-3.4*10^38 ~ 3.4*10^38
	-- float64: 64位浮点数，占用8个字节，范围是-1.8*10^308 ~ 1.8*10^308

	- 布尔型 默认 false
	-- 布尔类型变量的默认值为false
	-- go 语言中不允许将整型强制转换为布尔型
	-- 布尔类型无法参与数值运算，也无法与其他类型进行转换

	- 字符串 默认 ""
	-- 转义符 \n \t \r \b \f \v \' \" \\ \0

	字节也叫Byte，是计算机数据的基本存储单位。8bit(位)=1Byte(字节)，1024Byte=1KB，1024KB=1MB，1024MB=1GB，1024GB=1TB。在电脑里一个中文占三个字节。

	复合数据类型：数组、切片、结构体、函数、map、通道（channel）、接口等
*/
